package main

import (
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"errors"
	"fmt"
	"github.com/tjfoc/gmsm/sm2"
	sm509 "github.com/tjfoc/gmsm/x509"
	"gmTool/sm2ext"
	"io/ioutil"
	"os"
)

func FileExist(path string) bool {
	_, err := os.Lstat(path)
	return !os.IsNotExist(err)
}

func Read_sm2_private_key_asn1(data []byte, passwd string) (*sm2.PrivateKey, error) {
	priKey, err := sm509.ParsePKCS8PrivateKey(data, []byte(passwd))
	if err != nil {
		if len(passwd) <= 0 {
			priKey, err = sm2ext.ParsePKCS8UnecryptedPrivateKey_openssl(data)
			if err != nil {
				priKey, err = sm2ext.ParsePKCS8UnecryptedPrivateKey_alipay(data)
			}
		}
	}

	return priKey, err
}

func Read_sm2_private_pem_file(pemFileName, passwd string) (*sm2.PrivateKey, error) {
	privateKeyPem, err := ioutil.ReadFile(pemFileName)
	if err != nil {
		fmt.Println("read file error:", err)
		return nil, err
	}

	var block *pem.Block
	block, _ = pem.Decode(privateKeyPem)
	if block == nil {
		return nil, errors.New("failed to decode private key")
	}

	return Read_sm2_private_key_asn1(block.Bytes, passwd)
}

func Read_sm2_public_pem_data(pemData []byte) (*sm2.PublicKey, error) {
	pubKey, err := sm509.ParseSm2PublicKey(pemData)
	if err != nil {
		pubKey, err = sm2ext.ParseSm2PublicKey_openssl(pemData)
	}
	return pubKey, err
}

func Read_sm2_public_pem_file(pemFileName string) (*sm2.PublicKey, error) {
	pemTmp, err := ioutil.ReadFile(pemFileName)
	if err != nil {
		fmt.Println("read file error:", err)
		return nil, err
	}

	block, _ := pem.Decode(pemTmp)
	if block == nil || block.Type != "PUBLIC KEY" {
		return nil, errors.New("failed to decode public key")
	}

	return Read_sm2_public_pem_data(block.Bytes)
}

func Read_rsa_private_pem_file(pemFileName, passwd string) (*rsa.PrivateKey, error) {
	pemData, err := ioutil.ReadFile(pemFileName)
	if err != nil {
		fmt.Println("read file error:", err)
		return nil, err
	}

	block, _ := pem.Decode(pemData)
	if block == nil {
		return nil, errors.New("private key error")
	}

	priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	return priKey.(*rsa.PrivateKey), err
}

func Read_rsa_public_pem_file(pemFileName string) (*rsa.PublicKey, error) {
	pemData, err := ioutil.ReadFile(pemFileName)
	if err != nil {
		fmt.Println("read file error:", err)
		return nil, err
	}

	block, _ := pem.Decode(pemData)
	if block == nil {
		return nil, errors.New("private key error")
	}

	priKey, err := x509.ParsePKIXPublicKey(block.Bytes)
	if err != nil {
		return nil, err
	}

	return priKey.(*rsa.PublicKey), err
}
